package com.one.resolve;

import com.alibaba.fastjson.JSON;
import com.one.annotation.RequestUser;
import com.one.constant.RedisPrefixConstant;
import com.one.util.RedisUtils;
import com.one.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.InvalidObjectException;
import java.util.Objects;

/**
 * @Author ShiWen
 * @date 2022/1/14 11:56
 * @Version 1.0
 * @Description TODO 请求用户信息解析器
 */
public class RequestUserResolver implements HandlerMethodArgumentResolver {
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        // 强制指定参数解析的注解和类型：方法的形参必须增加指定的自定义注解@RequestUser,
        // 且注解需要被解析为指定的目标参数对象（——解析的类型和参数类型要相同）

        return methodParameter.hasParameterAnnotation(RequestUser.class)
                && methodParameter.getParameterType().isAssignableFrom(UserVo.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        // 不穿token时返回null对象

        if (Objects.isNull(nativeWebRequest.getHeader("token")))
            return null;

        // 必须满足上面指定的条件，才可以执行注解解析为目标参数对象 （supportsParameter必须返回true)
        // 自动从redis中获取token对象的用户信息字符串，转换为目标实体对象 （前提：必须满足请求权限许可校验）
        Object userObj = redisUtils.get(RedisPrefixConstant.LOGIN_TOKEN+nativeWebRequest.getHeader("token"));
        if (Objects.isNull(userObj)) {

            return null;
        }
        // 返回目标实体对象
        return JSON.parseObject(userObj.toString(), UserVo.class);
    }
}
